﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Xml;
using Microsoft.SharePoint;
using Microsoft.SharePoint.PowerShell;

using Microsoft.Office.Server.Search.Administration;
using Microsoft.Office.Server.Search.Cmdlet;
using Microsoft.Office.Server.Search.Query;

namespace Community.SharePoint.PowerShell
{
    /// <summary>
    /// SharePoint PowerShell Community Kit
    /// Get-SPEnterpriseSearchQueryResults
    /// This PowerShell cmdlet tests a query of SharePoint Enterprise Search and
    /// returns an XmlDocument with results.
    /// Example (Queries Enterprise Search for the term "accounting" and saves the results as an XML file): 
    /// $searchapp = Get-SPEnterpriseSearchServiceApplication "Search Service Application"
    /// (Get-SPEnterpriseSearchQueryResults -SearchApplication $searchapp -query "accounting").Save("c:\scripts\SearchResults.xml")
    /// Author: Corey Roth (@coreyroth)
    /// Creation Date: 8/15/2010
    /// </summary>
    [Cmdlet(VerbsCommon.Get, "SPEnterpriseSearchQueryResults")]
    public class GetEnterpriseSearchQueryResults : SPGetCmdletBase<XmlDocument>
    {
        private const string defaultLocationName = "LocalSearchIndex";
        private const string defaultSearchServiceApplicationProxyName = "Search Service Application";

        private string location;
        private string searchServiceApplicationProxyName;

        [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0)]
        public SearchServiceApplicationPipeBind SearchApplication { get; set; }

        [Parameter(Mandatory = true, Position = 1), Alias(new string[] { "q" })] 
        public string Query { get; set; }

        [Parameter(Mandatory = false, Position = 2), Alias(new string[] { "l" }), DefaultValue(defaultLocationName)]
        public string Location 
        { 
            get
            {
                if (!string.IsNullOrEmpty(location))
                    return location;
                else
                    return defaultLocationName;
            }
            set
            {
                location = value;
            }
        }

        [Parameter(Mandatory = false, Position = 3), Alias(new string[] { "p" }), DefaultValue(defaultSearchServiceApplicationProxyName)]
        public string SearchServiceApplicationProxyName
        {
            get
            {
                if (!string.IsNullOrEmpty(searchServiceApplicationProxyName))
                    return searchServiceApplicationProxyName;
                else
                    return defaultSearchServiceApplicationProxyName;
            }
            set
            {
                searchServiceApplicationProxyName = value;
            }
        }

        [Parameter(Mandatory = false)]
        public int? StartItem { get; set; }

        [Parameter(Mandatory = false)]
        public int? ItemsPerPage { get; set; }


        /// <summary>
        /// Return an XmlDocument with search results.
        /// </summary>
        /// <returns></returns>
        protected override IEnumerable<XmlDocument> RetrieveDataObjects()
        {
            // get the service application
            SearchServiceApplication searchServiceApplication = SearchApplication.Read();

            // get the search service application proxy - there is probably a better way to do this
            var searchProxy = (SearchServiceApplicationProxy)searchServiceApplication.ServiceApplicationProxyGroup.Proxies.FirstOrDefault(p => p.Name == SearchServiceApplicationProxyName);

            QueryManager queryManager = new QueryManager();
            LocationList locationList = new LocationList();

            // add the federated location we want - LocalSearchIndex by default
            Location localSearchLocation = new Location(Location, searchProxy);

            // set the start page and page size
            if (StartItem.HasValue)
                localSearchLocation.StartItem = StartItem.Value;

            if (ItemsPerPage.HasValue)
                localSearchLocation.ItemsPerPage = ItemsPerPage.Value;

            // not including managed properties for nows
            //            localSearchLocation.RequestedProperties = new System.Collections.Specialized.StringCollection()
            //{ "workid", "rank", "title", "author", "size", "write", "path", "sitename", "description",
            //    "CollapsingStatus", "HitHighlightedSummary", "HitHighlightedProperties", "ContentClass",
            //    "IsDocument", "PictureThumbnailURL", "PopularSocialTags", "PictureWidth", "PictureHeight",
            //    "DatePictureTaken", "ServerRedirectedURL", "DocumentType" };

            // add the Location to the LocationList
            locationList.Add(localSearchLocation);

            // set the query
            queryManager.UserQuery = Query;
            queryManager.Add(locationList);
            queryManager.IsTriggered(locationList);

            // make the call to search
            XmlDocument xmlDocument = queryManager.GetResults(locationList);

            return new List<XmlDocument>(){xmlDocument};
        }
    }
}
